package com.pioneer.cloudstorage.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.tika.Tika;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

@Slf4j
@Service
public class FileContentParserService {

    @Value("${file.index.max-content-length:100000}")
    private int maxContentLength;

    private final Tika tika = new Tika();
    private final Parser parser = new AutoDetectParser();

    /**
     * 解析文件内容
     */
    public String parseFileContent(InputStream inputStream, String mimeType, String fileName) {
        try {
            // 根据文件类型选择最优解析方式
            if (mimeType == null) {
                mimeType = tika.detect(inputStream);
            }

            String content;

            // 针对不同类型使用不同的解析策略
            if ("application/pdf".equals(mimeType)) {
                content = parsePdfContent(inputStream);
            } else if (mimeType.startsWith("text/")) {
                content = parseTextContent(inputStream);
            } else if (mimeType.contains("word") || mimeType.contains("excel") ||
                    mimeType.contains("powerpoint") || mimeType.contains("presentation")) {
                content = parseOfficeDocument(inputStream);
            } else {
                content = parseWithTika(inputStream);
            }

            // 限制内容长度
            if (content != null && content.length() > maxContentLength) {
                content = content.substring(0, maxContentLength);
                log.info("文件内容过长，已截断: {}", fileName);
            }

            return content;

        } catch (Exception e) {
            log.error("解析文件内容失败: {}", fileName, e);
            return null;
        }
    }

    /**
     * 使用 Tika 通用解析
     */
    private String parseWithTika(InputStream inputStream) throws IOException, TikaException, SAXException {
        BodyContentHandler handler = new BodyContentHandler(maxContentLength);
        Metadata metadata = new Metadata();
        ParseContext context = new ParseContext();

        parser.parse(inputStream, handler, metadata, context);
        return handler.toString();
    }

    /**
     * 专门解析 PDF 文件（PDFBox 通常比 Tika 更准确）
     */
    private String parsePdfContent(InputStream inputStream) throws TikaException, IOException, SAXException {
        try (PDDocument document = PDDocument.load(inputStream)) {
            PDFTextStripper stripper = new PDFTextStripper();
            stripper.setSortByPosition(true);
            return stripper.getText(document);
        } catch (IOException e) {
            log.warn("PDFBox 解析失败，回退到 Tika 解析", e);
            return parseWithTika(inputStream);
        }
    }

    /**
     * 解析文本文件
     */
    private String parseTextContent(InputStream inputStream) throws IOException {
        byte[] bytes = inputStream.readAllBytes();
        // 尝试检测编码
        String content = new String(bytes, StandardCharsets.UTF_8);
        // 清理文本，移除过多空白字符
        return content.replaceAll("\\s+", " ").trim();
    }

    /**
     * 解析 Office 文档
     */
    private String parseOfficeDocument(InputStream inputStream) {
        try {
            return parseWithTika(inputStream);
        } catch (Exception e) {
            log.warn("Office 文档解析失败", e);
            return null;
        }
    }

    /**
     * 检查是否支持内容索引的文件类型
     */
    public boolean isIndexableType(String mimeType) {
        if (mimeType == null) return false;

        return mimeType.startsWith("text/") ||
                mimeType.equals("application/pdf") ||
                mimeType.equals("application/msword") ||
                mimeType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document") ||
                mimeType.equals("application/vnd.ms-excel") ||
                mimeType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") ||
                mimeType.equals("application/vnd.ms-powerpoint") ||
                mimeType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation") ||
                mimeType.equals("application/rtf") ||
                mimeType.equals("text/markdown") ||
                mimeType.equals("application/x-tex");
    }
}